// compile with: gcc -O -c temporizacao.c

#include "temporizacao.h"

// Inicia temporizacao de uso da CPU.  Em multicores, os tempos sao somados.
// O resultdo da temporizacao inclui os tempos de CPU de todos os cores utilizados.
void CPUTimingStart() {
	cpuTime = clock();
}

// Termina temporizacao de tempo de CPU
void CPUTimingStop() {
	cpuTime = clock() - cpuTime;
}

// Termina temporizacao de tempo de CPU e Imprime os resultados no formato hora:min:seg.mseg.useg
void CPUTimingStopAndPrint(char *mess) {
	cpuTime = clock() - cpuTime;
	printTime(mess, cpuTime);
}

// Inicia temporizacao
void ElapsedTimingStart() {
	if(gettimeofday(&tp0, 0)) {
		myPrintf("\n*** Erro na chamada gettimeofday() ***  (enter para continuar):");
		return;
	}
}

// Termina temporizacao
void ElapsedTimingStop() {
	if(gettimeofday(&tp1, 0)) {
		myPrintf("\n*** Erro na chamada gettimeofday() ***  (enter para continuar):");
		return ;
	}
	elapsedTime = (tp1.tv_sec - tp0.tv_sec)*1000000 + (tp1.tv_usec - tp0.tv_usec);
}

// Termina temporizacao e Imprime os resultados no formato hora:min-seg.mseg+useg
void ElapsedTimingStopAndPrint(char *mess) {
	ElapsedTimingStop();
	printTime(mess, elapsedTime);
}

// Start measuring CPU and elapsed time.
void startTiming(timeBundle *tb) {
	tb->cTime = clock();
	if(gettimeofday(&tb->inicio, 0)) {
		myPrintf("\n*** Erro na chamada gettimeofday() ***  (enter para continuar):");
		return;
	}
}

// stopTiming(&t1) Stop measuring the CPU and Elapsed time relative to t1.
// Requires a previous call to startTiming(&t1)
void stopTiming(timeBundle *tb) {
	if(gettimeofday(&tb->fim, 0)) {
		myPrintf("\n*** Erro na chamada gettimeofday() ***  (enter para continuar):");
		return ;
	}
	tb->eTime = (tb->fim.tv_sec - tb->inicio.tv_sec)*1000000 + 
					  (tb->fim.tv_usec - tb->inicio.tv_usec);
	tb->cTime = clock() - tb->cTime;
}
	
// formataTempo: retorna string contendo o tempo t (originalmente em microsegundos)
// no formato horaHminMsegSmsegMSusegU.  Somente os dois valores mais significativos sao
// impressos.  Excecao para quando h, min, seg e mseg forem zero, quando somente o valor
// de useg eh impresso.
char *formatTime(char *s, clock_t t) {
	int min, seg, mseg, useg;
	useg = (clock_t) t % 1000;
	mseg = ((clock_t) t/1000) % 1000;
	t /= CLOCKS_PER_SEC;
	seg =  t % 60;
	t /= 60;
	min =  t % 60;
	t /= 60;
	if (t) 
		sprintf(s,"%dh%02dm", (int) t, min);
	else if (min)
		sprintf(s, "%dm%02ds", min, seg);
	else if (seg)
		sprintf(s, "%ds%03dms", seg, mseg);
	else if (mseg)
		sprintf(s, "%dms%03du", mseg, useg);
	else 
		sprintf(s, "%du", useg);
		
	return s;
}


// Formats the timeBundle tb as "ElapsedTime (CPUTime)" each as "hour:min:sec.msec.usec"
// Uses the smallest possible string.
// Returns the number of chars in s (not including the trailing '\0'.
int formatTimeBundle(timeBundle *tb, char *s) {
	char s1[20], s2[20];
	formatTime(s1, tb->eTime);
	formatTime(s2, tb->cTime);
	return sprintf(s, "%s (%s)", s1, s2);
}

// Imprimi time no fomrmato hora:min:seg.mseg.useg.  Se COUNT estiver definido,
// imprimi # function calls cf/1000, # comparisons cc/1000, # operations co/1000,
// and # comparisons + operations (cc+c0)/1000
void printTime(char *mess, clock_t time) {
	int size;
	sTime[0] = 0;
	size = strlen(formatTime(sTime, time));

#ifdef COUNT
	printf("%s %9lldK %11lldK %11lldK %11lldK %17s", mess, cf/1000, cc/1000, co/1000,
		   (long long) (cc+co)/1000, sTime);
#else
	printf("%s    %s", mess, sTime);
#endif
	fflush(stdout);
}

/* Exemplo de uso das funcoes para temporizacao

#include "formataTempo.h"
int main(void) {
	ElapsedTimingStart();
	CPUTimingStart();
	
	// insira aqui os comandos a ser temporizados ...
	dummy();

	CPUTimingStopAndPrint("dummy() CPU time:");
	ElapsedTimingStopAndPrint("dummy() elapsed time:");
}
*/
